package com.ruoyi.common.utils.qrCode;


import cn.hutool.extra.qrcode.BufferedImageLuminanceSource;
import com.google.zxing.*;
import com.google.zxing.client.j2se.MatrixToImageConfig;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import com.ruoyi.common.config.RuoYiConfig;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * @ClassName 二维码工具类
 * @Description TODO
 * @Author luguanqing
 * @Date 2020/11/13 10:08
 * @Version 1.0
 */
public class QrCode {

    //设置图片宽高和缩放比例
    private static final int IMAGE_WIDTH = 80;
    private static final int IMAGE_HEIGHT = 80;
    private static final int IMAGE_HALF_WIDTH = IMAGE_WIDTH/2;
    private static final int FRAME_WIDTH = 2;


    /**
     * 生成二维码
     * @Param context 二维码内容
     * @Param width 二维码宽度
     * @Param height 二维码高度
     */
    public  void encodeQRcode(String context, int width, int height, String filePath){
        try {
            String format = "png";// 图像类型
            HashMap hints = new HashMap();
            //内容编码格式
            hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
            // 指定纠错等级
            hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
            //设置二维码边的空度，非负数
            hints.put(EncodeHintType.MARGIN, 1);
            BitMatrix bitMatrix = new MultiFormatWriter().encode(context, BarcodeFormat.QR_CODE, width, height, hints);
            MatrixToImageWriter.writeToPath(bitMatrix, format, new File(filePath).toPath());// 输出原图片
            MatrixToImageConfig matrixToImageConfig = new MatrixToImageConfig(0xFF000001, 0xFFFFFFFF);
            System.out.println("生成二维码成功!");
        }catch (Exception ex) {
            Logger.getLogger(QrCode.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    /**
     * 对图片进行缩放
     * @param imgPath 图片路径
     * @param width 图片缩放后的宽度
     * @param height 图片缩放后的高度
     * @param hasFiller 是否补白
     * @return
     */
    public  BufferedImage scale(String imgPath,int width,int height,boolean hasFiller){
        double ratio = 0.0; // 缩放比例
        File file = new File(imgPath);
        BufferedImage srcImage = null;
        try {
            srcImage = ImageIO.read(file);
        } catch (IOException ex) {
            Logger.getLogger(QrCode.class.getName()).log(Level.SEVERE, null, ex);
        }
        Image finalImage;
        finalImage = srcImage.getScaledInstance(width, height,BufferedImage.SCALE_SMOOTH);
        // 计算比例
        if ((srcImage.getHeight() > height) || (srcImage.getWidth() > width)) {
            if (srcImage.getHeight() > srcImage.getWidth()) {
                ratio = (new Integer(height)).doubleValue()/ srcImage.getHeight();
            } else {
                ratio = (new Integer(width)).doubleValue()/ srcImage.getWidth();
            }
            AffineTransformOp op = new AffineTransformOp(AffineTransform.getScaleInstance(ratio, ratio), null);
            finalImage = op.filter(srcImage, null);
        }
        if (hasFiller) {// 补白
            BufferedImage image = new BufferedImage(width, height,BufferedImage.TYPE_INT_RGB);
            Graphics2D graphic = image.createGraphics();
            graphic.setColor(Color.white);
            graphic.fillRect(0, 0, width, height);
            if (width == finalImage.getWidth(null)){
                graphic.drawImage(finalImage, 0,(height - finalImage.getHeight(null))/2,finalImage.getWidth(null), finalImage.getHeight(null),Color.white, null);
            }else{
                graphic.drawImage(finalImage,(width - finalImage.getWidth(null))/2,0,finalImage.getWidth(null), finalImage.getHeight(null),Color.white, null);
                graphic.dispose();
                finalImage = image;
            }
        }
        return (BufferedImage) finalImage;
    }

    /**
     * 获取生成二维码图片
     */
    public  BufferedImage  QRcode(String context, int width, int height) throws Exception{
        BufferedImage qrCode=null;
        String format = "png";// 图像类型
        HashMap hints = new HashMap();
        //内容编码格式
        hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
        // 指定纠错等级
        hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
        //设置二维码边的空度，非负数
        hints.put(EncodeHintType.MARGIN, 1);
        BitMatrix bitMatrix = new MultiFormatWriter().encode(context, BarcodeFormat.QR_CODE, width, height, hints);
        qrCode = MatrixToImageWriter.toBufferedImage(bitMatrix);
        return qrCode;
    }

    /**
     * 报告生成二维码
     */
    public String reportQrcode(String url, String reportNum) throws Exception {
        String filepath = RuoYiConfig.getQrPath() + "/" + reportNum + ".png";
        QrCode qrCode = new QrCode();
        qrCode.logoQrCode(url, 512,512,filepath);
        return filepath;
    }

    /**
     * 生成带有logo标志的二维码
     */
    public  void encodeLogoQRcode(BufferedImage matrixImage, File logoFile, String fileName) throws Exception{
        /**
         * 读取二维码图片，并构建绘图对象
         */
        Graphics2D g2 = matrixImage.createGraphics();

        int matrixWidth = matrixImage.getWidth();
        int matrixHeigh = matrixImage.getHeight();

        /**
         * 读取Logo图片
         */
        BufferedImage logo = ImageIO.read(logoFile);

        //开始绘制图片
        g2.drawImage(logo,matrixWidth/5*2,matrixHeigh/5*2, matrixWidth/5, matrixHeigh/5, null);//绘制
        BasicStroke stroke = new BasicStroke(5,BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND);
        g2.setStroke(stroke);// 设置笔画对象
        //指定弧度的圆角矩形
        RoundRectangle2D.Float round = new RoundRectangle2D.Float(matrixWidth/5*2, matrixHeigh/5*2, matrixWidth/5, matrixHeigh/5,20,20);
        g2.setColor(Color.white);
        g2.draw(round);// 绘制圆弧矩形

        //设置logo 有一道灰色边框
        BasicStroke stroke2 = new BasicStroke(1,BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND);
        g2.setStroke(stroke2);// 设置笔画对象
        RoundRectangle2D.Float round2 = new RoundRectangle2D.Float(matrixWidth/5*2+2, matrixHeigh/5*2+2, matrixWidth/5-4, matrixHeigh/5-4,20,20);
        g2.setColor(new Color(128,128,128));
        g2.draw(round2);// 绘制圆弧矩形

        g2.dispose();
        matrixImage.flush() ;
        ImageIO.write(matrixImage, "png", new File(fileName));
    }

    /**
     * 生成带logo的二维码图片
     */
    public  void logoQrCode( String context, int width, int height, String fileName) throws Exception{
        BufferedImage bufferedImage = QRcode(context, width, height);
        //logo图片
        File files = new File("D:\\ahyz.png");
        encodeLogoQRcode(bufferedImage, files, fileName);
    }

    /**
     * 解析读取二维码
     * @param qrCodePath 二维码图片路径
     * @return
     */
    public  String decodeQRcode(String qrCodePath){
        BufferedImage image;
        String qrCodeText = null;
        try {
            image = ImageIO.read(new File(qrCodePath));
            LuminanceSource source = new BufferedImageLuminanceSource(image);
            Binarizer binarizer = new HybridBinarizer(source);
            BinaryBitmap binaryBitmap = new BinaryBitmap(binarizer);
            Map<DecodeHintType, Object> hints = new HashMap<DecodeHintType, Object>();
            hints.put(DecodeHintType.CHARACTER_SET, "UTF-8");
            // 对图像进行解码
            Result result = new MultiFormatReader().decode(binaryBitmap, hints);
            qrCodeText = result.getText();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (NotFoundException e) {
            e.printStackTrace();
        }
        return qrCodeText;
    }

}
